//! 数字类型(数)的完整实现
//!
//! 设计原则：
//! - 内部统一使用 f64 存储
//! - 整数和浮点数无缝转换
//! - 显示时智能判断（整数不显示小数点）
//! - 支持完整的数学运算和方法

use crate::interpreter::method::{Method, MethodType};
use crate::interpreter::value::{Value, ValueData};
use std::collections::HashMap;

/// 数字类型常量定义
pub mod number_constants {
    /// 圆周率
    pub const PI: f64 = std::f64::consts::PI;
    /// 自然对数的底
    pub const E: f64 = std::f64::consts::E;
    /// 最大安全整数
    pub const MAX_SAFE_INTEGER: f64 = 9007199254740991.0; // 2^53 - 1
    /// 最小安全整数
    pub const MIN_SAFE_INTEGER: f64 = -9007199254740991.0;
    /// 正无穷大
    pub const POSITIVE_INFINITY: f64 = f64::INFINITY;
    /// 负无穷大
    pub const NEGATIVE_INFINITY: f64 = f64::NEG_INFINITY;
    /// NaN (非数字)
    pub const NAN: f64 = f64::NAN;
}

/// 数字类型的内置方法实现
pub struct NumberMethods;

impl NumberMethods {
    /// 创建数字类型的所有内置方法
    pub fn create_all_methods() -> HashMap<String, Method> {
        let mut methods = HashMap::new();

        // 基本数学运算方法
        methods.insert("取整".to_string(), Self::create_floor_method());
        methods.insert("四舍五入".to_string(), Self::create_round_method());
        methods.insert("绝对值".to_string(), Self::create_abs_method());
        methods.insert("平方根".to_string(), Self::create_sqrt_method());
        methods.insert("幂".to_string(), Self::create_pow_method());

        // 高级数学方法
        methods.insert("向上取整".to_string(), Self::create_ceil_method());
        methods.insert("向下取整".to_string(), Self::create_floor_method()); // 别名
        methods.insert("截断".to_string(), Self::create_trunc_method());
        methods.insert("符号".to_string(), Self::create_sign_method());
        methods.insert("倒数".to_string(), Self::create_reciprocal_method());

        // 三角函数
        methods.insert("正弦".to_string(), Self::create_sin_method());
        methods.insert("余弦".to_string(), Self::create_cos_method());
        methods.insert("正切".to_string(), Self::create_tan_method());
        methods.insert("反正弦".to_string(), Self::create_asin_method());
        methods.insert("反余弦".to_string(), Self::create_acos_method());
        methods.insert("反正切".to_string(), Self::create_atan_method());

        // 对数函数
        methods.insert("自然对数".to_string(), Self::create_ln_method());
        methods.insert("常用对数".to_string(), Self::create_log10_method());
        methods.insert("二进制对数".to_string(), Self::create_log2_method());

        // 比较方法
        methods.insert("是否正数".to_string(), Self::create_is_positive_method());
        methods.insert("是否负数".to_string(), Self::create_is_negative_method());
        methods.insert("是否零".to_string(), Self::create_is_zero_method());
        methods.insert("是否整数".to_string(), Self::create_is_integer_method());
        methods.insert("是否有限".to_string(), Self::create_is_finite_method());
        methods.insert("是否无穷".to_string(), Self::create_is_infinite_method());
        methods.insert("是否NaN".to_string(), Self::create_is_nan_method());

        // 常量方法
        methods.insert("圆周率".to_string(), Self::create_pi_method());
        methods.insert("自然常数".to_string(), Self::create_e_method());

        // 范围方法
        methods.insert("限制范围".to_string(), Self::create_clamp_method());
        methods.insert("取最小".to_string(), Self::create_min_method());
        methods.insert("取最大".to_string(), Self::create_max_method());

        methods
    }

    /// 创建取整方法（向下取整）
    fn create_floor_method() -> Method {
        Method::native(MethodType::Number, |args| {
            if let ValueData::Number(n) = &args[0].data {
                Ok(Value::number(n.floor()))
            } else {
                Err("不是数字类型".to_string())
            }
        })
    }

    /// 创建四舍五入方法
    fn create_round_method() -> Method {
        Method::native(MethodType::Number, |args| {
            if let ValueData::Number(n) = &args[0].data {
                Ok(Value::number(n.round()))
            } else {
                Err("不是数字类型".to_string())
            }
        })
    }

    /// 创建绝对值方法
    fn create_abs_method() -> Method {
        Method::native(MethodType::Number, |args| {
            if let ValueData::Number(n) = &args[0].data {
                Ok(Value::number(n.abs()))
            } else {
                Err("不是数字类型".to_string())
            }
        })
    }

    /// 创建平方根方法
    fn create_sqrt_method() -> Method {
        Method::native(MethodType::Number, |args| {
            if let ValueData::Number(n) = &args[0].data {
                if *n < 0.0 {
                    Err("不能对负数取平方根".to_string())
                } else {
                    Ok(Value::number(n.sqrt()))
                }
            } else {
                Err("不是数字类型".to_string())
            }
        })
    }

    /// 创建幂运算方法
    fn create_pow_method() -> Method {
        Method::native(MethodType::Number, |args| {
            if let (ValueData::Number(base), ValueData::Number(exponent)) =
                (&args[0].data, &args[1].data)
            {
                Ok(Value::number(base.powf(*exponent)))
            } else {
                Err("幂运算需要两个数字参数".to_string())
            }
        })
    }

    /// 创建向上取整方法
    fn create_ceil_method() -> Method {
        Method::native(MethodType::Number, |args| {
            if let ValueData::Number(n) = &args[0].data {
                Ok(Value::number(n.ceil()))
            } else {
                Err("不是数字类型".to_string())
            }
        })
    }

    /// 创建截断方法（去掉小数部分）
    fn create_trunc_method() -> Method {
        Method::native(MethodType::Number, |args| {
            if let ValueData::Number(n) = &args[0].data {
                Ok(Value::number(n.trunc()))
            } else {
                Err("不是数字类型".to_string())
            }
        })
    }

    /// 创建符号方法（返回-1、0或1）
    fn create_sign_method() -> Method {
        Method::native(MethodType::Number, |args| {
            if let ValueData::Number(n) = &args[0].data {
                if n.is_nan() {
                    Ok(Value::number(f64::NAN))
                } else {
                    Ok(Value::number(n.signum()))
                }
            } else {
                Err("不是数字类型".to_string())
            }
        })
    }

    /// 创建倒数方法
    fn create_reciprocal_method() -> Method {
        Method::native(MethodType::Number, |args| {
            if let ValueData::Number(n) = &args[0].data {
                if *n == 0.0 {
                    Err("不能对零取倒数".to_string())
                } else {
                    Ok(Value::number(1.0 / n))
                }
            } else {
                Err("不是数字类型".to_string())
            }
        })
    }

    /// 创建正弦方法
    fn create_sin_method() -> Method {
        Method::native(MethodType::Number, |args| {
            if let ValueData::Number(n) = &args[0].data {
                Ok(Value::number(n.sin()))
            } else {
                Err("不是数字类型".to_string())
            }
        })
    }

    /// 创建余弦方法
    fn create_cos_method() -> Method {
        Method::native(MethodType::Number, |args| {
            if let ValueData::Number(n) = &args[0].data {
                Ok(Value::number(n.cos()))
            } else {
                Err("不是数字类型".to_string())
            }
        })
    }

    /// 创建正切方法
    fn create_tan_method() -> Method {
        Method::native(MethodType::Number, |args| {
            if let ValueData::Number(n) = &args[0].data {
                Ok(Value::number(n.tan()))
            } else {
                Err("不是数字类型".to_string())
            }
        })
    }

    /// 创建反正弦方法
    fn create_asin_method() -> Method {
        Method::native(MethodType::Number, |args| {
            if let ValueData::Number(n) = &args[0].data {
                if *n < -1.0 || *n > 1.0 {
                    Err("反正弦函数的参数必须在[-1, 1]范围内".to_string())
                } else {
                    Ok(Value::number(n.asin()))
                }
            } else {
                Err("不是数字类型".to_string())
            }
        })
    }

    /// 创建反余弦方法
    fn create_acos_method() -> Method {
        Method::native(MethodType::Number, |args| {
            if let ValueData::Number(n) = &args[0].data {
                if *n < -1.0 || *n > 1.0 {
                    Err("反余弦函数的参数必须在[-1, 1]范围内".to_string())
                } else {
                    Ok(Value::number(n.acos()))
                }
            } else {
                Err("不是数字类型".to_string())
            }
        })
    }

    /// 创建反正切方法
    fn create_atan_method() -> Method {
        Method::native(MethodType::Number, |args| {
            if let ValueData::Number(n) = &args[0].data {
                Ok(Value::number(n.atan()))
            } else {
                Err("不是数字类型".to_string())
            }
        })
    }

    /// 创建自然对数方法
    fn create_ln_method() -> Method {
        Method::native(MethodType::Number, |args| {
            if let ValueData::Number(n) = &args[0].data {
                if *n <= 0.0 {
                    Err("自然对数的参数必须为正数".to_string())
                } else {
                    Ok(Value::number(n.ln()))
                }
            } else {
                Err("不是数字类型".to_string())
            }
        })
    }

    /// 创建常用对数方法（以10为底）
    fn create_log10_method() -> Method {
        Method::native(MethodType::Number, |args| {
            if let ValueData::Number(n) = &args[0].data {
                if *n <= 0.0 {
                    Err("常用对数的参数必须为正数".to_string())
                } else {
                    Ok(Value::number(n.log10()))
                }
            } else {
                Err("不是数字类型".to_string())
            }
        })
    }

    /// 创建二进制对数方法（以2为底）
    fn create_log2_method() -> Method {
        Method::native(MethodType::Number, |args| {
            if let ValueData::Number(n) = &args[0].data {
                if *n <= 0.0 {
                    Err("二进制对数的参数必须为正数".to_string())
                } else {
                    Ok(Value::number(n.log2()))
                }
            } else {
                Err("不是数字类型".to_string())
            }
        })
    }

    /// 创建是否正数方法
    fn create_is_positive_method() -> Method {
        Method::native(MethodType::Number, |args| {
            if let ValueData::Number(n) = &args[0].data {
                Ok(Value::boolean(*n > 0.0))
            } else {
                Err("不是数字类型".to_string())
            }
        })
    }

    /// 创建是否负数方法
    fn create_is_negative_method() -> Method {
        Method::native(MethodType::Number, |args| {
            if let ValueData::Number(n) = &args[0].data {
                Ok(Value::boolean(*n < 0.0))
            } else {
                Err("不是数字类型".to_string())
            }
        })
    }

    /// 创建是否零方法
    fn create_is_zero_method() -> Method {
        Method::native(MethodType::Number, |args| {
            if let ValueData::Number(n) = &args[0].data {
                Ok(Value::boolean(*n == 0.0))
            } else {
                Err("不是数字类型".to_string())
            }
        })
    }

    /// 创建是否整数方法
    fn create_is_integer_method() -> Method {
        Method::native(MethodType::Number, |args| {
            if let ValueData::Number(n) = &args[0].data {
                Ok(Value::boolean(n.fract() == 0.0))
            } else {
                Err("不是数字类型".to_string())
            }
        })
    }

    /// 创建是否有限方法
    fn create_is_finite_method() -> Method {
        Method::native(MethodType::Number, |args| {
            if let ValueData::Number(n) = &args[0].data {
                Ok(Value::boolean(n.is_finite()))
            } else {
                Err("不是数字类型".to_string())
            }
        })
    }

    /// 创建是否无穷方法
    fn create_is_infinite_method() -> Method {
        Method::native(MethodType::Number, |args| {
            if let ValueData::Number(n) = &args[0].data {
                Ok(Value::boolean(n.is_infinite()))
            } else {
                Err("不是数字类型".to_string())
            }
        })
    }

    /// 创建是否NaN方法
    fn create_is_nan_method() -> Method {
        Method::native(MethodType::Number, |args| {
            if let ValueData::Number(n) = &args[0].data {
                Ok(Value::boolean(n.is_nan()))
            } else {
                Err("不是数字类型".to_string())
            }
        })
    }

    /// 创建圆周率常量方法
    fn create_pi_method() -> Method {
        Method::native(MethodType::Number, |_args| {
            Ok(Value::number(number_constants::PI))
        })
    }

    /// 创建自然常数方法
    fn create_e_method() -> Method {
        Method::native(MethodType::Number, |_args| {
            Ok(Value::number(number_constants::E))
        })
    }

    /// 创建限制范围方法（将值限制在指定范围内）
    fn create_clamp_method() -> Method {
        Method::native(MethodType::Number, |args| {
            if let (ValueData::Number(value), ValueData::Number(min), ValueData::Number(max)) =
                (&args[0].data, &args[1].data, &args[2].data)
            {
                if min > max {
                    Err("最小值不能大于最大值".to_string())
                } else {
                    Ok(Value::number(value.clamp(*min, *max)))
                }
            } else {
                Err("限制范围需要三个数字参数".to_string())
            }
        })
    }

    /// 创建取最小值方法（返回多个数中的最小值）
    fn create_min_method() -> Method {
        Method::native(MethodType::Number, |args| {
            if args.len() < 2 {
                return Err("取最小值需要至少两个参数".to_string());
            }

            let mut min_val = f64::INFINITY;
            for arg in args.iter().skip(1) {
                // 跳过self
                if let ValueData::Number(n) = &arg.data {
                    if *n < min_val {
                        min_val = *n;
                    }
                } else {
                    return Err("所有参数必须是数字类型".to_string());
                }
            }

            Ok(Value::number(min_val))
        })
    }

    /// 创建取最大值方法（返回多个数中的最大值）
    fn create_max_method() -> Method {
        Method::native(MethodType::Number, |args| {
            if args.len() < 2 {
                return Err("取最大值需要至少两个参数".to_string());
            }

            let mut max_val = f64::NEG_INFINITY;
            for arg in args.iter().skip(1) {
                // 跳过self
                if let ValueData::Number(n) = &arg.data {
                    if *n > max_val {
                        max_val = *n;
                    }
                } else {
                    return Err("所有参数必须是数字类型".to_string());
                }
            }

            Ok(Value::number(max_val))
        })
    }
}

/// 数字类型转换器
pub struct NumberConverter;

impl NumberConverter {
    /// 将值转换为数字
    pub fn convert_to_number(value: &Value) -> Result<f64, String> {
        match &value.data {
            ValueData::Number(n) => Ok(*n),
            ValueData::String(s) => Self::parse_string_to_number(s),
            ValueData::Boolean(b) => Ok(if *b { 1.0 } else { 0.0 }),
            ValueData::Null => Ok(0.0),
            // 空容器转换为0
            ValueData::List(elements) => Ok(if elements.borrow().is_empty() {
                0.0
            } else {
                1.0
            }),
            ValueData::Dict(items) => Ok(if items.borrow().is_empty() { 0.0 } else { 1.0 }),
            ValueData::Set(items) => Ok(if items.borrow().is_empty() { 0.0 } else { 1.0 }),
            // 其他类型默认转换为1
            _ => Ok(1.0),
        }
    }

    /// 解析字符串为数字
    fn parse_string_to_number(s: &str) -> Result<f64, String> {
        // 首先尝试直接解析为浮点数
        if let Ok(n) = s.parse::<f64>() {
            return Ok(n);
        }

        // 支持中文数字转换
        match s.trim() {
            "零" => Ok(0.0),
            "一" => Ok(1.0),
            "二" => Ok(2.0),
            "三" => Ok(3.0),
            "四" => Ok(4.0),
            "五" => Ok(5.0),
            "六" => Ok(6.0),
            "七" => Ok(7.0),
            "八" => Ok(8.0),
            "九" => Ok(9.0),
            "十" => Ok(10.0),
            "十一" => Ok(11.0),
            "十二" => Ok(12.0),
            "十三" => Ok(13.0),
            "十四" => Ok(14.0),
            "十五" => Ok(15.0),
            "十六" => Ok(16.0),
            "十七" => Ok(17.0),
            "十八" => Ok(18.0),
            "十九" => Ok(19.0),
            "二十" => Ok(20.0),
            "百" => Ok(100.0),
            "千" => Ok(1000.0),
            "万" => Ok(10000.0),
            "亿" => Ok(100000000.0),
            _ => Err(format!("无法将字符串 '{}' 转换为数字", s)),
        }
    }

    /// 将数字转换为字符串（智能显示）
    pub fn convert_to_string(n: f64) -> String {
        // 特殊值处理
        if n.is_nan() {
            return "NaN".to_string();
        }
        if n.is_infinite() {
            return if n > 0.0 {
                "正无穷".to_string()
            } else {
                "负无穷".to_string()
            };
        }

        // 智能显示：整数不显示小数点
        if n == n.floor() {
            format!("{}", n as i64)
        } else {
            // 限制小数位数，避免精度问题
            let rounded = (n * 1e10).round() / 1e10;
            format!("{}", rounded)
        }
    }

    /// 检查两个数字是否相等（考虑浮点精度）
    pub fn are_numbers_equal(a: f64, b: f64, epsilon: Option<f64>) -> bool {
        let eps = epsilon.unwrap_or(f64::EPSILON);
        (a - b).abs() < eps
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_number_methods_creation() {
        let methods = NumberMethods::create_all_methods();

        // 检查基本方法是否存在
        assert!(methods.contains_key("取整"));
        assert!(methods.contains_key("四舍五入"));
        assert!(methods.contains_key("绝对值"));
        assert!(methods.contains_key("平方根"));
        assert!(methods.contains_key("幂"));

        // 检查高级方法是否存在
        assert!(methods.contains_key("向上取整"));
        assert!(methods.contains_key("截断"));
        assert!(methods.contains_key("符号"));

        // 检查三角函数是否存在
        assert!(methods.contains_key("正弦"));
        assert!(methods.contains_key("余弦"));
        assert!(methods.contains_key("正切"));

        // 检查比较方法是否存在
        assert!(methods.contains_key("是否正数"));
        assert!(methods.contains_key("是否负数"));
        assert!(methods.contains_key("是否零"));
        assert!(methods.contains_key("是否整数"));
    }

    #[test]
    fn test_number_converter() {
        // 测试字符串到数字的转换
        assert_eq!(
            NumberConverter::parse_string_to_number("123.45").unwrap(),
            123.45
        );
        assert_eq!(NumberConverter::parse_string_to_number("一").unwrap(), 1.0);
        assert_eq!(NumberConverter::parse_string_to_number("十").unwrap(), 10.0);

        // 测试无效字符串
        assert!(NumberConverter::parse_string_to_number("无效").is_err());

        // 测试数字到字符串的智能显示
        assert_eq!(NumberConverter::convert_to_string(42.0), "42");
        assert_eq!(NumberConverter::convert_to_string(3.14159), "3.14159");
        assert_eq!(NumberConverter::convert_to_string(f64::NAN), "NaN");
    }

    #[test]
    fn test_number_equality() {
        assert!(NumberConverter::are_numbers_equal(1.0, 1.0, None));
        assert!(NumberConverter::are_numbers_equal(1.0 + 2.0, 3.0, None));
        assert!(!NumberConverter::are_numbers_equal(1.0, 2.0, None));

        // 测试浮点精度
        assert!(NumberConverter::are_numbers_equal(
            0.1 + 0.2,
            0.3,
            Some(1e-10)
        ));
    }
}
